package cloud.health.common.file.infrastructure;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Slf4j
public abstract class AbstractNettyServer {

    private static final int SO_BACKLOG = 1024;

    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private ServerBootstrap bootstrap;

    protected abstract String name();

    protected abstract int port();

    protected abstract ChannelInitializer<SocketChannel> channelInitializer();

    @PostConstruct
    protected void init() {
        log.info("post");
        // 创建两个线程组 boosGroup、workerGroup
        this.bossGroup = new NioEventLoopGroup();
        this.workerGroup = new NioEventLoopGroup();
        // 创建服务端的启动对象，设置参数
        this.bootstrap = new ServerBootstrap();
        // 设置两个线程组boosGroup和workerGroup
        bootstrap.group(this.bossGroup, this.workerGroup)
                // 设置服务端通道实现类型
                .channel(NioServerSocketChannel.class)
                // 设置线程队列得到连接个数
                .option(ChannelOption.SO_BACKLOG, SO_BACKLOG)
                // 开启了Nagle算法
                .childOption(ChannelOption.TCP_NODELAY, true)
                // 设置保持活动连接状态
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                // 给workerGroup的EventLoop对应的管道设置处理器
                .childHandler(this.channelInitializer());
        try {
            this.bootstrap.bind(this.port()).sync();
            log.info("{} listen on {} start success", this.name(), this.port());
        } catch (Exception e) {
            log.error("{} listen on {} start error -->", this.name(), this.port(), e);
        }
    }

    @PreDestroy
    protected void shutdown() {
        log.info("destroy");
        this.bossGroup.shutdownGracefully();
        this.workerGroup.shutdownGracefully();
    }

}
